package com.apkdv.mvvmfast.network

import com.apkdv.mvvmfast.network.config.HttpCode
import com.apkdv.mvvmfast.entity.BaseResult
import com.apkdv.mvvmfast.network.exception.ApiException
import rxhttp.wrapper.annotation.Parser
import rxhttp.wrapper.parse.TypeParser
import rxhttp.wrapper.utils.convertTo
import java.lang.reflect.Type


/**
 *
 * 如果使用协程发送请求，wrappers属性可不设置，设置了也无效
 */
@Parser(name = "Response")
open class ResponseParser<T> : TypeParser<T> {
    /**
     * 此构造方法适用于任意Class对象，但更多用于带泛型的Class对象，如：List<Student>
     *
     * 用法:
     * Java: .asParser(new ResponseParser<List<Student>>(){})
     * Kotlin: .asParser(object : ResponseParser<List<Student>>() {})
     *
     * 注：此构造方法一定要用protected关键字修饰，否则调用此构造方法将拿不到泛型类型
     */
    protected constructor() : super()

    private val defaultMsg = "数据请求异常"

    /**
     * 此构造方法仅适用于不带泛型的Class对象，如: Student.class
     *
     * 用法
     * Java: .asParser(new ResponseParser<>(Student.class))   或者  .asResponse(Student.class)
     * Kotlin: .asParser(ResponseParser(Student::class.java)) 或者  .asResponse<Student>()
     */
    constructor(type: Type) : super(type)

    @Throws(ApiException::class)
    override fun onParse(response: okhttp3.Response): T {
        try {
            val data: BaseResult<T> = response.convertTo(BaseResult::class, *types)
            var t = data.getData() //获取data字段
            if (t == null && types[0] === String::class.java) {
                /*
                 * 考虑到有些时候服务端会返回：{"errorCode":0,"errorMsg":"关注成功"}  类似没有data的数据
                 * 此时code正确，但是data字段为空，直接返回data的话，会报空指针错误，
                 * 所以，判断泛型为String类型时，重新赋值，并确保赋值不为null
                 */
                @Suppress("UNCHECKED_CAST")
                t = data.getMsg() as T
            }
            if (!data.isSuccess()) { //code不等于200，说明数据不正确，抛出异常
                throw ApiException(
                    data.getCode(),
                    data.getMsg() ?: defaultMsg,
                    response.body.toString()
                )
            }
            return t
        } catch (e: Exception) {
            if (e is ApiException) {
                throw e
            } else
                throw ApiException(
                    HttpCode.HTTP.INNER_EXCEPTION.toLong(),
                    defaultMsg,
                    response.body.toString()
                )
        }
    }
}